package com.woniuxy.reservation.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woniuxy.reservation.infra.model.Reservation;
import com.woniuxy.reservation.infra.mapper.ReservationMapper;
import com.woniuxy.reservation.service.ReservationService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniuxy.reservation.service.servicedto.ReservationServiceDto;
import com.woniuxy.reservation.service.serviceparam.InsertReservationServiceParam;
import com.woniuxy.reservation.service.serviceparam.SearchReservationByConditionServiceParam;
import com.woniuxy.reservation.service.serviceparam.UpdateReservationStateServiceParam;
import com.woniuxy.table.client.TableQueryClient;
import com.woniuxy.table.client.TableTypeQueryClient;
import com.woniuxy.table.client.result.DinnerTableTypeClientDto;
import com.woniuxy.table.client.result.TableClientDto;
import common.WoniuPage;
import exception.MallException;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import result.CommonResultCodeEnum;
import result.Result;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 预约表 服务实现类
 * </p>
 *
 * @author Lucas
 * @since 2023-07-21
 */
@Service
public class ReservationServiceImpl extends ServiceImpl<ReservationMapper, Reservation> implements ReservationService {

    @Autowired
    private ReservationMapper reservationMapper;
    @Autowired
    private TableQueryClient tableQueryClient;
    @Autowired
    private TableTypeQueryClient tableTypeQueryClient;
    @Override
    @GlobalTransactional
    public void insertReservation(InsertReservationServiceParam param) {
        QueryWrapper<Reservation> reservationQueryWrapper = new QueryWrapper<>();
        reservationQueryWrapper.eq("link_phone",param.getLinkPhone()).eq("store_id",param.getStoreId()).eq("reservation_state","WAITING");
        Reservation reservation = reservationMapper.selectOne(reservationQueryWrapper);
        if (reservation!=null) {
            throw new MallException("同一个号码不能多次预约",CommonResultCodeEnum.INVALID_PARAM);
        }
        if (param.getReservationTime().before(new Date())) {
            throw new MallException("不能预约比现在更早的时间",CommonResultCodeEnum.INVALID_PARAM);
        }
        Reservation reservationNew = BeanUtil.toBean(param, Reservation.class);
        reservationNew.setCommitTime(new Date());
        reservationNew.setReservationState("WAITING");
        save(reservationNew);
    }

    @Override
    @GlobalTransactional
    public void updateReservationState(UpdateReservationStateServiceParam param) {
        QueryWrapper<Reservation> reservationQueryWrapper = new QueryWrapper<>();
        reservationQueryWrapper.eq("store_id",param.getStoreId()).eq("reservation_id",param.getReservationId());
        Reservation reservation = reservationMapper.selectOne(reservationQueryWrapper);
        if (reservation==null) {
            throw new MallException("当前预约不存在", CommonResultCodeEnum.INVALID_PARAM);
        }
        if (reservation.getReservationState().equals(param.getReservationState())) {
            throw new MallException("当前预约已是当前状态", CommonResultCodeEnum.INVALID_PARAM);
        }
        if (param.getAllocationTableId()!=null) {
            Result<TableClientDto> storeTableByTable = tableQueryClient.getStoreTableByTable(param.getAllocationTableId());
            TableClientDto tableClientDto = storeTableByTable.getData();
            if (tableClientDto.getStoreId()!=param.getStoreId()) {
                throw new MallException("当前餐桌不存在", CommonResultCodeEnum.INVALID_PARAM);
            }
        }
        //预定状态 待处理 WAITING | 预约成功 SUCCESS| 预约失败 FAIL | 已到店 PROMISED  | 逾期 OVERDUE
        if (reservation.getReservationState().equals("WAITING")&&((!param.getReservationState().equals("SUCCESS"))&&(!param.getReservationState().equals("FAIL")))) {
            throw new MallException("当前状态为待处理，不可以进行预约成功或者预约失败的其他操作", CommonResultCodeEnum.INVALID_PARAM);
        }
        if (reservation.getReservationState().equals("SUCCESS")&&((!param.getReservationState().equals("PROMISED"))&&(!param.getReservationState().equals("OVERDUE")))) {
            throw new MallException("当前状态为预约成功，不可以进行已到店或者逾期的其他操作", CommonResultCodeEnum.INVALID_PARAM);
        }
        if (reservation.getReservationState().equals("FAIL")) {
            throw new MallException("当前状态为预约失败，不可以进行其他操作", CommonResultCodeEnum.INVALID_PARAM);
        }
        if (reservation.getReservationState().equals("PROMISED")) {
            throw new MallException("当前状态为已到店，不可以进行其他操作", CommonResultCodeEnum.INVALID_PARAM);
        }
        if (reservation.getReservationState().equals("OVERDUE")) {
            throw new MallException("当前状态为逾期，不可以进行其他操作", CommonResultCodeEnum.INVALID_PARAM);
        }

        reservation.setReservationState(param.getReservationState());
        reservationMapper.updateById(reservation);
    }

    @Override
    @GlobalTransactional
    public void deleteReservation(Integer storeId, Integer reservationId) {
        QueryWrapper<Reservation> reservationQueryWrapper = new QueryWrapper<>();
        reservationQueryWrapper.eq("store_id",storeId).eq("reservation_id",reservationId);
        Reservation reservation = reservationMapper.selectOne(reservationQueryWrapper);
        if (reservation==null) {
            throw new MallException("当前预约不存在", CommonResultCodeEnum.INVALID_PARAM);
        }
        reservationMapper.deleteById(reservationId);
    }

    @Override
    public WoniuPage<ReservationServiceDto> searchReservationByCondition(SearchReservationByConditionServiceParam param) {
        QueryWrapper<Reservation> reservationQueryWrapper = new QueryWrapper<>();
        reservationQueryWrapper.eq("store_id",param.getStoreId());
        if (param.getMemberId()!=null) {
            reservationQueryWrapper.eq("member_id",param.getMemberId());
        }
        if (param.getCompartment()!=null) {
            reservationQueryWrapper.eq("compartment",param.getCompartment());
        }
        if (param.getKeyword()!=null&&!"".equals(param.getKeyword())) {
            reservationQueryWrapper.and(wrapper->wrapper.like("link_phone",param.getKeyword())).or().like("allocation_table_num",param.getKeyword());
        }
        if (param.getReservationState()!=null&&!"".equals(param.getReservationState())) {
            reservationQueryWrapper.eq("reservation_state",param.getReservationState());
        }
        if (param.getStartTime()!=null) {
            reservationQueryWrapper.ge("reservation_time",param.getStartTime());
        }
        if (param.getEndTime()!=null) {
            reservationQueryWrapper.le("reservation_time",param.getEndTime());
        }
        Integer pageNum=param.getPageIndex();
        Integer pageSize=param.getPageSize();
        if (pageNum==null) {
            pageNum=1;
        }
        if (pageSize==null) {
            pageSize=5;
        }
        Page<Reservation> page = new Page<>(pageNum, pageSize);
        reservationMapper.selectPage(page,reservationQueryWrapper);
        WoniuPage<ReservationServiceDto> woniuPage = new WoniuPage<>();
        woniuPage.setTotal(page.getTotal());
        woniuPage.setPages(page.getPages());
        woniuPage.setPageIndex(page.getCurrent());
        woniuPage.setPageSize(page.getSize());
        List<ReservationServiceDto> reservationServiceDtos = new ArrayList<>();
        for (Reservation reservation : page.getRecords()) {
            ReservationServiceDto reservationServiceDto = BeanUtil.toBean(reservation, ReservationServiceDto.class);
            if (reservationServiceDto.getCompartment()==1) {
                reservationServiceDto.setCompartmentName("是");
            }
            if (reservationServiceDto.getCompartment()==2) {
                reservationServiceDto.setCompartmentName("否");
            }

            if (reservation.getAllocationTableId()!=null) {
                Result<TableClientDto> storeTableByTable = tableQueryClient.getStoreTableByTable(reservation.getAllocationTableId());
                TableClientDto tableClientDto = storeTableByTable.getData();
                if (tableClientDto.getStoreId()!=reservation.getStoreId()) {
                    throw new MallException("当前餐桌不存在", CommonResultCodeEnum.INVALID_PARAM);
                }
                Result<DinnerTableTypeClientDto> result = tableTypeQueryClient.getTableType(reservation.getStoreId(), tableClientDto.getTableTypeId());
                DinnerTableTypeClientDto dinnerTableTypeClientDto = result.getData();
                if (dinnerTableTypeClientDto==null) {
                    throw new MallException("当前餐桌类型不存在",CommonResultCodeEnum.INVALID_PARAM);
                }
                reservationServiceDto.setAllocationTableNum(tableClientDto.getTableNum());
                reservationServiceDto.setTableTypeName(dinnerTableTypeClientDto.getTableTypeName());
            }
            reservationServiceDtos.add(reservationServiceDto);
        }
        woniuPage.setList(reservationServiceDtos);
        return woniuPage;
    }
}
